1 module hip.hiprenderer.backend.gl.defaultshaders;
2 import hip.api.renderer.core;
3 import hip.config.renderer;
4 private enum GLDefaultShadersPath = __MODULE__;
5 
6 
7 static if(!HasOpenGL)
8 {
9     immutable DefaultShader[] DefaultShaders;
10 }
11 else:
12 
13 immutable DefaultShader[] DefaultShaders = [
14     HipShaderPresets.DEFAULT: DefaultShader(GLDefaultShadersPath, &getDefaultVertex, &getDefaultVertex),
15     HipShaderPresets.FRAME_BUFFER: DefaultShader(GLDefaultShadersPath, &getFrameBufferVertex, &getFrameBufferFragment),
16     HipShaderPresets.GEOMETRY_BATCH: DefaultShader(GLDefaultShadersPath, &getGeometryBatchVertex, &getGeometryBatchFragment),
17     HipShaderPresets.SPRITE_BATCH: DefaultShader(GLDefaultShadersPath, &getSpriteBatchVertex, &getSpriteBatchFragment),
18     HipShaderPresets.BITMAP_TEXT: DefaultShader(GLDefaultShadersPath, &getBitmapTextVertex, &getBitmapTextFragment),
19     HipShaderPresets.NONE: DefaultShader(GLDefaultShadersPath)
20 ];
21 
22 
23 private {
24 
25     version(GLES32) version = GLES3;
26     version(GLES30) version = GLES3;
27 
28     version(GLES3)
29     {
30         enum shaderVersion = "#version 300 es";
31         enum floatPrecision = "precision mediump float;";
32         // enum floatPrecision = "";
33     }
34     else version(GLES20)
35     {
36         enum shaderVersion = "#version 100";
37         enum floatPrecision = "precision mediump float;";
38     }
39     else
40     {
41         enum shaderVersion = "#version 330 core";
42         enum floatPrecision = "";
43     }
44 
45     import hip.util.conv;
46     import hip.util.format: fastUnsafeCTFEFormat, format;
47 
48 
49 
50     private string getBaseFragment()
51     {
52         __gshared string baseShader;
53         if(baseShader is null)
54         {
55             string defs;
56             version(WebAssembly) defs~= "#define WASM\n";
57             version(PSVita) defs~= "#define PSVITA\n";
58             baseShader = shaderVersion~"\n"~floatPrecision~"\n"~defs ~
59     `#ifdef WASM
60         #define TEXTURE_2D texture2D
61     #elif defined(PSVITA)
62         #define TEXTURE_2D texture2D
63     #else
64         #define TEXTURE_2D texture
65     #endif`;
66 
67         }
68         return baseShader;
69     }
70 
71 
72 
73     string getDefaultFragment()
74     {
75         return getBaseFragment~q{
76 
77             uniform vec4 globalColor;
78             in vec4 vertexColor;
79             in vec2 tex_uv;
80             uniform sampler2D tex1;
81             out vec4 outPixelColor;
82 
83             void main()
84             {
85                 outPixelColor = vertexColor*globalColor*TEXTURE_2D(tex1, tex_uv);
86             }
87         };
88     }
89     string getFrameBufferFragment()
90     {
91         return getBaseFragment~q{
92 
93             in vec2 inTexST;
94             uniform sampler2D uBufferTexture;
95             uniform vec4 uColor;
96             out vec4 outPixelColor;
97 
98             void main()
99             {
100                 vec4 col = TEXTURE_2D(uBufferTexture, inTexST);
101                 float grey = (col.r+col.g+col.b)/3.0;
102                 outPixelColor = grey * uColor;
103             }
104         };
105     }
106 
107     version(GLES20) //They are very different, so, better to keep them separate
108     {
109         string getSpriteBatchFragment()
110         {
111             import hip.hiprenderer.renderer;
112             int sup = HipRenderer.getMaxSupportedShaderTextures();
113             string textureSlotSwitchCase;
114             if(sup == 1) textureSlotSwitchCase = "gl_FragColor = TEXTURE_2D(uTex[0], inTexST)*inVertexColor*uBatchColor;\n";
115             else
116             {
117                 for(int i = 0; i < sup; i++)
118                 {
119                     string strI = to!string(i);
120                     if(i != 0)
121                         textureSlotSwitchCase~="\t\t\t\telse ";
122                     textureSlotSwitchCase~="if(texId == "~strI~")"~
123                     "{gl_FragColor = TEXTURE_2D(uTex["~strI~"], inTexST)*inVertexColor*uBatchColor;}\n";
124                 }
125             }
126             textureSlotSwitchCase~="}\n";
127             enum shaderSource = q{
128                 uniform vec4 uBatchColor;
129 
130                 varying vec4 inVertexColor;
131                 varying vec2 inTexST;
132                 varying float inTexID;
133 
134                 void main()
135             };
136 
137 
138             return getBaseFragment~format!q{
139                     uniform sampler2D uTex[%s];}(sup)~
140                 shaderSource~
141             "{"~q{
142                     int texId = int(inTexID);
143             }~ textureSlotSwitchCase;
144         }
145     }
146     else
147     {
148         string getSpriteBatchFragment()
149         {
150             import hip.hiprenderer.renderer;
151             int sup = HipRenderer.getMaxSupportedShaderTextures();
152             //Push the line breaks for easier debugging on gpu debugger
153             string textureSlotSwitchCase = "switch(texId)\n{\n";
154             for(int i = 0; i < sup; i++)
155             {
156                 string strI = to!string(i);
157                 textureSlotSwitchCase~="case "~strI~": "~
158                 "\t\toutPixelColor = TEXTURE_2D(uTex["~strI~"], inTexST)*inVertexColor*uBatchColor;break;\n";
159             }
160             textureSlotSwitchCase~="}\n";
161 
162                 enum shaderSource = q{
163 
164                     uniform vec4 uBatchColor;
165 
166                     in vec4 inVertexColor;
167                     in vec2 inTexST;
168                     in float inTexID;
169 
170                     out vec4 outPixelColor;
171                     void main()
172                 };
173             return getBaseFragment~format!q{
174                     uniform sampler2D uTex[%s];}(sup)~
175                 shaderSource~
176             "{"~q{
177                     int texId = int(inTexID);
178             } ~textureSlotSwitchCase~
179             "}";
180             // outPixelColor = texture(uTex[texId], inTexST)* inVertexColor * uBatchColor;
181             // outPixelColor = vec4(texId, texId, texId, 1.0)* inVertexColor * uBatchColor;
182         }
183 
184     }
185     string getGeometryBatchFragment()
186     {
187         version(GLES20)
188         {
189             enum attr1 = q{varying};
190             enum outputPixelVar = q{};
191             enum outputAssignment = q{gl_FragColor};
192         }
193         else
194         {
195             enum attr1 = q{in};
196             enum outputPixelVar = q{out vec4 outPixelColor;};
197             enum outputAssignment = q{outPixelColor};
198         }
199         enum shaderSource = q{
200             uniform vec4 uGlobalColor;
201             %s vec4 inVertexColor;
202             %s
203 
204             void main()
205             {
206                 %s = inVertexColor * uGlobalColor;
207             }
208         }.fastUnsafeCTFEFormat(attr1, outputPixelVar, outputAssignment);
209         return getBaseFragment~shaderSource;
210     }
211 
212     string getBitmapTextFragment()
213     {
214         version(GLES20)
215         {
216             enum attr1 = q{varying};
217             enum outputPixelVar = q{};
218             enum outputAssignment = q{gl_FragColor};
219         }
220         else
221         {
222             enum attr1 = q{in};
223             enum outputPixelVar = q{out vec4 outPixelColor;};
224             enum outputAssignment = q{outPixelColor};
225         }
226         enum shaderSource = q{
227 
228 
229             uniform vec4 uColor;
230             uniform sampler2D uTex;
231             %s vec2 inTexST;
232             %s
233 
234             void main()
235             {
236                 float r = TEXTURE_2D(uTex, inTexST).r;
237                 %s = vec4(r,r,r,r)*uColor;
238             }
239         }.fastUnsafeCTFEFormat(attr1, outputPixelVar, outputAssignment);
240         return getBaseFragment~shaderSource;
241     }
242 
243 
244     // //getSDFFragment
245     // string getBitmapTextFragment()
246     // {
247     //     version(GLES20)
248     //     {
249     //         enum attr1 = q{varying};
250     //         enum outputPixelVar = q{};
251     //         enum outputAssignment = q{gl_FragColor};
252     //     }
253     //     else
254     //     {
255     //         enum attr1 = q{in};
256     //         enum outputPixelVar = q{out vec4 outPixelColor;};
257     //         enum outputAssignment = q{outPixelColor};
258     //     }
259 
260     //     enum shaderSource = q{
261     //     %s vec2 inTexST;
262     //     %s
263 
264     //     uniform sampler2D uTex;
265     //     // uniform vec4 bgColor;
266     //     uniform vec4 uColor;
267 
268     //     float screenPxRange = 4.5;
269 
270     //     void main() {
271     //         float sd = texture(uTex, inTexST).r;
272     //         float screenPxDistance = screenPxRange*(sd - 0.5);
273     //         float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0);
274     //         // color = mix(bgColor, fgColor, opacity);
275     //         %s = uColor * opacity;
276     //     }}.fastUnsafeCTFEFormat(attr1, outputPixelVar, outputAssignment);
277 
278     //     return getBaseFragment~shaderSource;
279     // }
280 
281 
282     string getDefaultVertex()
283     {
284         return shaderVersion~"\n"~floatPrecision~"\n"~q{
285 
286             layout (location = 0) in vec3 position;
287             layout (location = 1) in vec4 color;
288             layout (location = 2) in vec2 texCoord;
289             uniform mat4 proj;
290 
291 
292             out vec4 vertexColor;
293             out vec2 tex_uv;
294 
295             void main()
296             {
297                 gl_Position = proj*vec4(position, 1.0);
298                 vertexColor = color;
299                 tex_uv = texCoord;
300             }
301         };
302     }
303     string getFrameBufferVertex()
304     {
305         return shaderVersion~"\n"~floatPrecision~"\n"~q{
306 
307             layout (location = 0) in vec2 vPosition;
308             layout (location = 1) in vec2 vTexST;
309 
310             out vec2 inTexST;
311 
312             void main()
313             {
314                 gl_Position = vec4(vPosition, 0.0, 1.0);
315                 inTexST = vTexST;
316             }
317         };
318     }
319     string getSpriteBatchVertex()
320     {
321         version(GLES20) //`in` representation in GLES 20 is `attribute``
322         {
323             enum attr1 = q{attribute};
324             enum attr2 = q{attribute};
325             enum attr3 = q{attribute};
326             enum attr4 = q{attribute};
327             enum out1 = q{varying};
328             enum out2 = q{varying};
329             enum out3 = q{varying};
330         }
331         else
332         {
333             enum attr1 = q{layout (location = 0) in};
334             enum attr2 = q{layout (location = 1) in};
335             enum attr3 = q{layout (location = 2) in};
336             enum attr4 = q{layout (location = 3) in};
337             enum out1 = q{out};
338             enum out2 = q{out};
339             enum out3 = q{out};
340         }
341         enum shaderSource = q{
342             %s vec3 vPosition;
343             %s vec4 vColor;
344             %s vec2 vTexST;
345             %s float vTexID;
346 
347             uniform mat4 uMVP;
348 
349             %s vec4 inVertexColor;
350             %s vec2 inTexST;
351             %s float inTexID;
352 
353             void main()
354             {
355                 gl_Position = uMVP*vec4(vPosition, 1.0);
356                 inVertexColor = vColor;
357                 inTexST = vTexST;
358                 inTexID = vTexID;
359             }
360         }.fastUnsafeCTFEFormat(attr1, attr2, attr3, attr4, out1, out2, out3);
361         return shaderVersion~"\n"~floatPrecision~"\n"~shaderSource;
362     }
363     string getGeometryBatchVertex()
364     {
365         version(GLES20)
366         {
367             enum attr1 = q{attribute};
368             enum attr2 = q{attribute};
369             enum out1 = q{varying};
370         }
371         else
372         {
373             enum attr1 = q{layout (location = 0) in};
374             enum attr2 = q{layout (location = 1) in};
375             enum out1 = q{out};
376         }
377 
378         enum shaderSource = q{
379 
380         %s vec3 vPosition;
381         %s vec4 vColor;
382 
383             uniform mat4 uMVP;
384 
385             %s vec4 inVertexColor;
386 
387             void main()
388             {
389                 gl_Position = uMVP*vec4(vPosition, 1.0);
390                 inVertexColor = vColor;
391             }
392         }.fastUnsafeCTFEFormat(attr1, attr2, out1);
393         return shaderVersion~"\n"~floatPrecision~"\n"~shaderSource;
394     }
395 
396     string getBitmapTextVertex()
397     {
398         version(GLES20)
399         {
400             enum attr1 = q{attribute};
401             enum attr2 = q{attribute};
402             enum out1 = q{varying};
403         }
404         else
405         {
406             enum attr1 = q{layout (location = 0) in};
407             enum attr2 = q{layout (location = 1) in};
408             enum out1 = q{out};
409         }
410         enum shaderSource = q{
411 
412             %s vec3 vPosition;
413             %s vec2 vTexST;
414 
415             uniform mat4 uMVP;
416 
417             %s vec2 inTexST;
418 
419             void main()
420             {
421                 gl_Position = uMVP * vec4(vPosition, 1.0);
422                 inTexST = vTexST;
423             }
424         }.fastUnsafeCTFEFormat(attr1, attr2, out1);
425         return shaderVersion~"\n"~floatPrecision~"\n"~shaderSource;
426     }
427 
428 }